import { createContext, useContext, useEffect, useState } from "react";
import { apiDictTree } from "~/api";
import type { DictType } from "~/common/enum/dict.enum";
import type { IDict } from "~/types/common";

type DictContextType = {
  dictsMap: Record<string, IDict[]>;
  dictMap: Record<string, IDict>;
  reloadDict: () => void;
};

const DictContext = createContext<DictContextType>({
  dictsMap: {},
  dictMap: {},
  reloadDict: () => {},
});

export function DictProvider({ children }: { children: React.ReactNode }) {
  const [dictsMap, setDictsMap] = useState<Partial<Record<DictType, IDict[]>>>(
    {},
  );
  const [dictMap, setDictMap] = useState<Record<string, IDict>>({});

  const _fetch = {
    init: async () => {
      const dicts = await apiDictTree();
      setDictsMap(
        dicts.reduce(
          (pre, cur) => {
            pre[cur.code] = cur.children || [];
            return pre;
          },
          {} as Record<string, IDict[]>,
        ),
      );
      // 递归处理dicts 处理dictMap
      const tempMap: Record<string, IDict> = {};
      const _handle = (dicts: IDict[]) => {
        for (const item of dicts) {
          tempMap[item.code] = item;
          if (item.children) {
            _handle(item.children);
          }
        }
        return tempMap;
      };
      setDictMap(_handle(dicts));
    },
  };

  const _handler = {
    reloadDict: async () => {
      console.log("reloadDict");
      _fetch.init();
    },
  };

  useEffect(() => {
    _fetch.init();
  }, []);

  return (
    <DictContext.Provider
      value={{ dictsMap, dictMap, reloadDict: _handler.reloadDict }}
    >
      {children}
    </DictContext.Provider>
  );
}

/**
 * 获取指定 key 的 dict 子级
 * @param key
 * @returns
 */
export function useDictsMap<T extends DictType>(
  keys: T[],
): Partial<Record<T, IDict[]>> {
  const context = useContext(DictContext);
  if (context === undefined) {
    throw new Error("useDictsMap must be used within a DictProvider");
  }
  let tempObj: Partial<Record<T, IDict[]>> = {};
  for (const item of keys) {
    tempObj[item] = context.dictsMap[item] || [];
  }
  return tempObj;
}

export function useDictMap(): Record<string, IDict> {
  const context = useContext(DictContext);
  if (context === undefined) {
    throw new Error("useDicts must be used within a DictProvider");
  }
  return context.dictMap;
}

export function useDictReload() {
  const context = useContext(DictContext);
  if (context === undefined) {
    throw new Error("useDicts must be used within a DictProvider");
  }
  return context.reloadDict;
}
